﻿using System;
using System.Collections.Generic;
using System.Text;
using hito = HenIT.BizTalk.Objects;

namespace HenIT.BizTalk.Report
{
    public class ReportWriter
    {
        public void CreateReport(hito.BizTalkGroup group, string groupName1, string groupName2)
        {
            Report.ReportViewer reportViewer = new Report.ReportViewer();
            reportViewer.WriteHeading("BizTalk Application Comparison");
            reportViewer.WriteLine(1, "Between");
            reportViewer.WriteLine(2, groupName1);
            reportViewer.WriteLine(1, "and");
            reportViewer.WriteLine(2, groupName2);
            reportViewer.WriteLine("");
            reportViewer.WriteHeading("Results");
            foreach (hito.Application hitApp in group.Applications)
            {
                reportViewer.WriteHeading2(1, hitApp.Name);
                if (!hitApp.Match)
                    reportViewer.WriteLineWarning(2, "Status - Application not found on BizTalk group 2!");
                else
                {
                    reportViewer.WriteLine(2, "Status - Match");

                    #region References
                    reportViewer.WriteHeading3(2, "References");
                    foreach (hito.StringMatch refApp in hitApp.References)
                    {
                        WriteStringMatchToReport(3, reportViewer, "Reference not found in destination application", refApp);
                    }
                    #endregion

                    #region Assemblies
                    reportViewer.WriteHeading3(2, "Assemblies");

                    if (hitApp.Assemblies.Count == 0)
                        reportViewer.WriteLine(3, "Status - No assemblies found");
                    else
                    {
                        foreach (hito.HitAssembly hitAssembly in hitApp.Assemblies)
                        {
                            reportViewer.WriteHeading3(3, hitAssembly.DisplayName);
                            if (!hitAssembly.Match)
                                reportViewer.WriteLineWarning(4, "Status - Assembly not found on BizTalk group 2!");
                            else if (!hitAssembly.Version.Match)
                            {
                                reportViewer.WriteLineWarning(4, "Status - Assembly version not found on BizTalk group 2!");
                            }
                            else if (!hitAssembly.Culture.Match)
                            {
                                reportViewer.WriteLineWarning(4, "Status - Assembly culture not found on BizTalk group 2!");
                            }
                            else
                            {
                                reportViewer.WriteLine(4, "Status - Match");
                                reportViewer.WriteHeading3(4, "Schemas");
                                foreach (hito.Schema schema in hitAssembly.Schemas)
                                {
                                    if (schema.Match)
                                    {
                                        reportViewer.WriteLine(5, schema.Name + " - Match");
                                    }
                                    else
                                    {
                                        reportViewer.WriteLineWarning(5, schema.Name + " - Schema not found in destination assembly");
                                    }
                                    reportViewer.WriteLine(6, schema.MessageType);
                                }

                                reportViewer.WriteHeading3(4, "Maps");
                                foreach (hito.StringMatch map in hitAssembly.Maps)
                                {
                                    WriteStringMatchToReport(5, reportViewer, "Map not found in destination assembly", map);
                                }

                                reportViewer.WriteHeading3(4, "Pipelines");
                                foreach (hito.StringMatch pipeline in hitAssembly.Pipelines)
                                {
                                    WriteStringMatchToReport(5, reportViewer, "Pipeline not found in destination assembly", pipeline);
                                }

                                reportViewer.WriteHeading3(4, "Orchestrations");
                                foreach (hito.Orchestration orchestration in hitAssembly.Orchestrations)
                                {
                                    if (!orchestration.Match)
                                        reportViewer.WriteLineWarning(5, "" + orchestration.Name + " - Orchestration not found in destination assembly");
                                    else
                                    {
                                        reportViewer.WriteLine(5, "" + orchestration.Name + " - Match");
                                        WriteStringMatchPropertyToReport(6, reportViewer, "Host", orchestration.Host);
                                        reportViewer.WriteHeading3(6, "Ports");
                                        foreach (hito.StringMatch port in orchestration.Ports)
                                        {
                                            WriteStringMatchToReport(7, reportViewer, "Port not found in destination orchestration", port);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    #region Ports
                    reportViewer.WriteHeading3(2, "Ports");
                    #region Receive ports
                    reportViewer.WriteHeading3(3, "Receive ports");
                    if (hitApp.ReceivePorts.Count == 0)
                        reportViewer.WriteLine(4, "Status - No Receive ports found");
                    else
                    {
                        foreach (hito.ReceivePort receivePort in hitApp.ReceivePorts)
                        {
                            reportViewer.WriteHeading3(4, receivePort.Name);
                            if (!receivePort.Match)
                                reportViewer.WriteLineWarning(5, "Status - Receive port not found on BizTalk group 2!");
                            else
                            {
                                WriteStringMatchPropertyToReport(5, reportViewer, "Is Two Way", receivePort.IsTwoWay);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Authentication type", receivePort.AuthenticationType);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Route Failed Messages", receivePort.RouteFailedMessage);

                                #region Receive locations
                                reportViewer.WriteHeading3(5, "Receive locations");
                                if (receivePort.Receivelocations.Count == 0)
                                    reportViewer.WriteLine(6, "Status - No Receive locations found");
                                else
                                {
                                    foreach (hito.ReceiveLocation receiveLocation in receivePort.Receivelocations)
                                    {
                                        reportViewer.WriteHeading3(6, receiveLocation.Name);
                                        if (!receiveLocation.Match)
                                            reportViewer.WriteLineWarning(7, "Status - Receive location not found on BizTalk group 2!");
                                        else
                                        {
                                            WriteStringMatchPropertyToReport(7, reportViewer, "Transport type", receiveLocation.TransportType);

                                            #region Pipelines
                                            WriteStringMatchPropertyToReport(7, reportViewer, "Receive pipeline", receiveLocation.ReceivePipeline);
                                            WriteMultiLineStringMatchPropertyToReport(7, reportViewer, "Receive pipeline data", receiveLocation.ReceivePipelineData);
                                            WriteStringMatchPropertyToReport(7, reportViewer, "Receive handler host", receiveLocation.ReceiveHandlerHost);
                                            if (receivePort.IsTwoWay.Value)
                                            {
                                                WriteStringMatchPropertyToReport(7, reportViewer, "Send pipeline", receiveLocation.SendPipeline);
                                                WriteMultiLineStringMatchPropertyToReport(7, reportViewer, "Send pipeline data", receiveLocation.SendPipelineData);
                                            } 
                                            #endregion

                                            WriteStringMatchPropertyToReport(7, reportViewer, "Is primary", receiveLocation.IsPrimary);

                                            #region Schedule
                                            WriteStringMatchPropertyToReport(7, reportViewer, "Start date enabled", receiveLocation.StartDateEnabled);
                                            if (receiveLocation.StartDateEnabled.Value || receiveLocation.StartDateEnabled.Value2)
                                            {
                                                WriteStringMatchPropertyToReport(7, reportViewer, "Start date", receiveLocation.StartDate);
                                            }
                                            WriteStringMatchPropertyToReport(7, reportViewer, "End date enabled", receiveLocation.EndDateEnabled);
                                            if (receiveLocation.EndDateEnabled.Value || receiveLocation.EndDateEnabled.Value2)
                                            {
                                                WriteStringMatchPropertyToReport(7, reportViewer, "End date", receiveLocation.EndDate);
                                            }
                                            WriteStringMatchPropertyToReport(7, reportViewer, "Service window enabled", receiveLocation.ServiceWindowEnabled);
                                            if (receiveLocation.ServiceWindowEnabled.Value || receiveLocation.ServiceWindowEnabled.Value2)
                                            {
                                                WriteStringMatchPropertyToReport(7, reportViewer, "From time", receiveLocation.FromTime);
                                                WriteStringMatchPropertyToReport(7, reportViewer, "To time", receiveLocation.ToTime);
                                            }
                                            #endregion
                                        }
                                    }
                                }
                                #endregion

                                #region Maps
                                if (receivePort.InboundMaps.Count > 0)
                                {
                                    reportViewer.WriteHeading3(5, "Inbound maps");
                                    foreach (hito.StringMatch map in receivePort.InboundMaps)
                                    {
                                        WriteStringMatchToReport(6, reportViewer, "Map not found in destination port", map);
                                    }
                                }
                                if (receivePort.OutboundMaps.Count > 0)
                                {
                                    reportViewer.WriteHeading3(5, "Outbound maps");
                                    foreach (hito.StringMatch map in receivePort.OutboundMaps)
                                    {
                                        WriteStringMatchToReport(6, reportViewer, "Map not found in destination port", map);
                                    }
                                }
                                #endregion
                            }
                        }
                    }
                    #endregion

                    #region Send ports
                    reportViewer.WriteHeading3(3, "Send ports");
                    if (hitApp.ReceivePorts.Count == 0)
                        reportViewer.WriteLine(4, "Status - No Send ports found");
                    else
                    {
                        foreach (hito.SendPort sendPort in hitApp.SendPorts)
                        {
                            reportViewer.WriteHeading3(4, sendPort.Name);
                            if (!sendPort.Match)
                                reportViewer.WriteLineWarning(5, "Status - Send port not found on BizTalk group 2!");
                            else
                            {
                                WriteStringMatchPropertyToReport(5, reportViewer, "Is Dynamic", sendPort.IsDynamic);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Is Two Way", sendPort.IsTwoWay);

                                #region Transports
                                if (!sendPort.IsDynamic.Value || !sendPort.IsDynamic.Value2)
                                {
                                    reportViewer.WriteHeading3(5, "Primary Transport");
                                    WriteStringMatchPropertyToReport(6, reportViewer, "Transport Type", sendPort.PrimaryTransport.TransportType);
                                    WriteStringMatchPropertyToReport(6, reportViewer, "Send Handler Host", sendPort.PrimaryTransport.SendHandlerHost);
                                    if (sendPort.SecondaryTransport.IsUsed.Value || !sendPort.SecondaryTransport.IsUsed.Match)
                                    {
                                        reportViewer.WriteHeading3(5, "Secondary Transport");
                                        WriteStringMatchPropertyToReport(6, reportViewer, "Transport Type", sendPort.SecondaryTransport.TransportType);
                                        WriteStringMatchPropertyToReport(6, reportViewer, "Send Handler Host", sendPort.SecondaryTransport.SendHandlerHost);
                                    }
                                } 
                                #endregion

                                #region Pipelines
                                if (sendPort.IsTwoWay.Value || sendPort.IsTwoWay.Value2)
                                {
                                    WriteStringMatchPropertyToReport(5, reportViewer, "Receive Pipeline", sendPort.ReceivePipeline);
                                    WriteMultiLineStringMatchPropertyToReport(5, reportViewer, "Receive Pipeline Data", sendPort.ReceivePipelineData);
                                    //reportViewer.WriteLineWarning(5, "Receive Pipeline Data property different");
                                    //reportViewer.WriteLineWarning(6, "Group 1: " + (sendPort.ReceivePipelineData.Name.Length == 0 ? "N/A" : sendPort.ReceivePipelineData.Name.ToString()));
                                    //reportViewer.WriteLineWarning(6, "Group 2: " + (sendPort.ReceivePipelineData.Name2.Length == 0 ? "N/A" : sendPort.ReceivePipelineData.Name2.ToString()));
                                }
                                WriteStringMatchPropertyToReport(5, reportViewer, "Send Pipeline", sendPort.SendPipeline);
                                WriteMultiLineStringMatchPropertyToReport(5, reportViewer, "Send Pipeline Data", sendPort.SendPipelineData);
                                #endregion

                                WriteStringMatchPropertyToReport(5, reportViewer, "Priority", sendPort.Priority);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Ordered delivery", sendPort.OrderedDelivery);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Stop sending on failure", sendPort.StopSendingOnFailure);
                                WriteStringMatchPropertyToReport(5, reportViewer, "Route Failed Messages", sendPort.RouteFailedMessage);

                                #region Maps
                                if (sendPort.InboundMaps.Count > 0)
                                {
                                    reportViewer.WriteHeading3(5, "Inbound maps");
                                    foreach (hito.StringMatch map in sendPort.InboundMaps)
                                    {
                                        WriteStringMatchToReport(6, reportViewer, "Map not found in destination port", map);
                                    }
                                }
                                if (sendPort.OutboundMaps.Count > 0)
                                {
                                    reportViewer.WriteHeading3(5, "Outbound maps");
                                    foreach (hito.StringMatch map in sendPort.OutboundMaps)
                                    {
                                        WriteStringMatchToReport(6, reportViewer, "Map not found in destination port", map);
                                    }
                                }
                                #endregion

                                WriteMultiLineStringMatchPropertyToReport(5, reportViewer, "Filter", sendPort.Filter);
                            }
                        }
                    }
                    #endregion
                    #endregion
                }
            }
            reportViewer.ShowDialog();
        }

        #region Write helpers
        private void WriteStringMatchToReport(int indentation, Report.ReportViewer reportViewer, string notFoundMsg, hito.StringMatch stringMatch)
        {
            if (!stringMatch.Match)
                reportViewer.WriteLineWarning(indentation, stringMatch.Name.ToString() + " - " + notFoundMsg);
            else
                reportViewer.WriteLine(indentation, stringMatch.Name.ToString() + " - Match");
        }
        private void WriteStringMatchPropertyToReport(int indentation, Report.ReportViewer reportViewer, string propertyName, hito.StringMatch stringMatch)
        {
            if (!stringMatch.Match)
                reportViewer.WriteLineWarning(indentation, propertyName + " property different - " + stringMatch.Name.ToString() + " - " + stringMatch.Name2.ToString());
            else
                reportViewer.WriteLine(indentation, propertyName + " property match - " + stringMatch.Name.ToString());
        }
        private void WriteStringMatchPropertyToReport(int indentation, Report.ReportViewer reportViewer, string propertyName, hito.BoolMatch boolMatch)
        {
            if (!boolMatch.Match)
                reportViewer.WriteLineWarning(indentation, propertyName + " property different - " + boolMatch.Value.ToString() + " - " + boolMatch.Value2.ToString());
            else
                reportViewer.WriteLine(indentation, propertyName + " property match - " + boolMatch.Value.ToString());
        }
        private void WriteStringMatchPropertyToReport(int indentation, Report.ReportViewer reportViewer, string propertyName, hito.IntMatch intMatch)
        {
            if (!intMatch.Match)
                reportViewer.WriteLineWarning(indentation, propertyName + " property different - " + intMatch.Value.ToString() + " - " + intMatch.Value2.ToString());
            else
                reportViewer.WriteLine(indentation, propertyName + " property match - " + intMatch.Value.ToString());
        }
        private void WriteStringMatchPropertyToReport(int indentation, Report.ReportViewer reportViewer, string propertyName, hito.DateTimeMatch dateTimeMatch)
        {
            if (!dateTimeMatch.Match)
                reportViewer.WriteLineWarning(indentation, propertyName + " property different - " + dateTimeMatch.Value.ToString() + " - " + dateTimeMatch.Value2.ToString());
            else
                reportViewer.WriteLine(indentation, propertyName + " property match - " + dateTimeMatch.Value.ToString());
        }
        private void WriteMultiLineStringMatchPropertyToReport(int indentation, Report.ReportViewer reportViewer, string propertyName, hito.StringMatch stringMatch)
        {
            if (!stringMatch.Match)
            {
                reportViewer.WriteLineWarning(indentation, propertyName + " different");
                reportViewer.WriteLineWarning(indentation + 1, "Group 1: " + (stringMatch.Name.Length == 0 ? "N/A" : stringMatch.Name.ToString()));
                reportViewer.WriteLineWarning(indentation + 1, "Group 2: " + (stringMatch.Name2.Length == 0 ? "N/A" : stringMatch.Name2.ToString()));
            }
            else
            {
                if (stringMatch.Name.Length == 0)
                    reportViewer.WriteLine(indentation, propertyName + " match - N/A");
                else
                {
                    reportViewer.WriteLine(indentation, propertyName + " match");
                    reportViewer.WriteLineWarning(indentation + 1, stringMatch.Name.ToString());
                }
            }
        }
        #endregion
    }
}
